package com.example.XueCuApp.Utils;

import android.content.Context;
import android.device.IccManager;
import android.device.ScanManager;
import android.os.Build;
import android.util.Log;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

public class A9LReader extends IDCardReader {
    private byte[] mBuffer = new byte[2320];
    private int mCurrentSize = 0;
    ScanManager mScanManager;
    //������Ϣ
    private final String sCmdReadSAMID = "AAAAAA9669000312FFEE";
    private final String sCmdFindCard = "AAAAAA96690003200122";
    private final String sCmdSelectCard = "AAAAAA96690003200221";
    private final String sCmdReadCardBase = "AAAAAA96690003300132";
    private final String sCmdReadNewAddress = "AAAAAA96690003300330";
    private final String sCmdReadCardFinger = "AAAAAA96690003301023";
    //�������Ϣ
    private final String sFIND_NO_CARD = "AAAAAA9669000400008084";
    private final String sFIND_SUCC = "AAAAAA9669000800009F0000000097";
    private final String sREAD_NO_CARD = "AAAAAA9669000400004145";
    private final String sSELECT_NO_CARD = "AAAAAA9669000400008185";
    private final String sSELECT_SUCC = "AAAAAA9669000C00009000000000000000009C";
    FileWriter localFileWriter;
    private static A9LReader self;
    private boolean flag = true;
    private boolean gpiokey = false;

    public static A9LReader getInstance(Context context) {
        if (self == null) {
            self = new A9LReader(context);
        }
        return self;
    }

    public A9LReader(Context theContext) {
        super(theContext);
        CODE = 1;
        TAG = "";
        PATH = "/dev/ttyHSL0";
        BAUDRATE = 115200;

    }

    public A9LReader(Context theContext, String sComPort, int nBaud) {
        super(theContext);
        CODE = 1;
        TAG = "A9LReader";
        PATH = sComPort;
        BAUDRATE = nBaud;


    }

    public boolean InitReader(byte[] byLicBuf) {
        String[] sRet = new String[1];
        Log.d(TAG, "InitReader  opening");
        readtimeout = 0;
		/*if(isOpen)	{
			Log.d(TAG,"InitReader  opened");
			return true;
			}*/
        try {
            Log.d(TAG, "PATH:" + PATH + "BAUDRATE:" + BAUDRATE);
            if (!openSerialPort(new File(PATH), BAUDRATE, 0)) {
                Log.d(TAG, "InitReader  opened failed " + PATH + BAUDRATE);
                return false;
            }
            Log.d(TAG, "InitReader  2222222222222  opened ok " + PATH + BAUDRATE);
        } catch (SecurityException e) {
            e.printStackTrace();
            isOpen = false;
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            isOpen = false;
            return false;
        }
        isOpen = true;
        return true;
    }

    public void ReleaseReader() {
        if (isOpen) {
            closeSerialPort();
            mCurrentSize = 0;
            isOpen = false;
        }
    }

    int readtimeout = 0;
    Timer timer = new Timer();
    TimerTask task = new TimerTask() {
        public void run() {
            readtimeout++;
            Log.i("wujinquan", "time " + readtimeout);
            if (readtimeout == 10) {
                if (gpiokey)
                    PowerOffReader();
                Log.i("wujinquan", "time 78");
                readtimeout = 0;
            }
        }
    };


    public boolean PowerOnReader() {
        Log.d(TAG, "A9LReader PowerOnReader");

        Log.i(TAG, "=====================PowerOnReader");


        if (flag) {
            timer.schedule(task, 60 * 1000, 60 * 1000);
            flag = false;
        }
        String Version = Build.VERSION.RELEASE;
        if (Version.equals("8.1.0")) {
            byte[] value = {1};
            byte rw = 0x02;
            byte io = 0x02;
            byte switchToPogoUsb = 0;
            android.device.PogoNative.seSwitchToPogoUsb(switchToPogoUsb);
            android.device.PogoNative.sePogoStatusRW(rw, io, value);
        } else {
            try {
                if (Version.equals("4.3")) {
                    FileWriter localFileWriter = new FileWriter(new File("sys/urovo_control/led/sys_gpio_ctl"));
                    localFileWriter.write("1");
                    localFileWriter.close();
                    gpiokey = true;
                    return true;
                } else {
                    byte[] arry1 = new byte[6];
                    com.ivsign.android.IDCReader.prop.getpropCharTojstringa(arry1);
                    String PRODUCT = new String(arry1, "GB2312");
                    Log.i(TAG, "PRODUCT:" + PRODUCT);

                    if (!PRODUCT.equals("SQ27TE") && !PRODUCT.equals("SQ27TC") ) {
                        Log.i(TAG, "mScanManager:" + "mScanManager close");
                        mScanManager = new ScanManager();
                        int scantype = mScanManager.getScannerType();
                        Log.i(TAG, "mScanType = " + scantype);
                        if (scantype!=13)//android 4710扫描头不需要关闭。3680需要关闭扫描头
                            mScanManager.closeScanner();
                        FileWriter gpiou = new FileWriter(new File("/sys/class/ugp_ctrl/gp_scan_debug_switch/enable"));
                        gpiou.write("0");
                        gpiou.close();
                    }
                    FileWriter localFileWriter = new FileWriter(new File("/sys/class/ugp_ctrl/gp_sys_5v_ctrl/enable"));
                    localFileWriter.write("1");
                    localFileWriter.close();
                    gpiokey = true;
                    return true;
                }
            } catch (IOException localIOException) {
                localIOException.printStackTrace();
                return false;
            }
        }
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        gpiokey = true;
        return true;


    }

    public boolean PowerOffReader() {
        Log.i(TAG, "=====================PowerOffReader");
        String Version = Build.VERSION.RELEASE;
        if (Version.equals("8.1.0")) {
            byte[] value = {0};
            byte rw = 0x02;
            byte io = 0x02;
            byte switchToPogoUsb = 1;
            //android.device.PogoNative.seSwitchToPogoUsb(switchToPogoUsb);
            android.device.PogoNative.sePogoStatusRW(rw, io, value);
        } else {
            try {
                if (Version.equals("4.3")) {
                    FileWriter localFileWriter = new FileWriter(new File("sys/urovo_control/led/sys_gpio_ctl"));
                    localFileWriter.write("0");
                    localFileWriter.close();
                    gpiokey = false;
                    return false;
                } else {
                    byte[] arry1 = new byte[6];
                    com.ivsign.android.IDCReader.prop.getpropCharTojstringa(arry1);
                    String PRODUCT = new String(arry1, "GB2312");
                    Log.i(TAG, "PRODUCT:" + PRODUCT);
                    if (!PRODUCT.equals("SQ27TE") && !PRODUCT.equals("SQ27TC")) {
                        mScanManager = new ScanManager();
                        mScanManager.openScanner();
                        FileWriter gpiou = new FileWriter(new File("/sys/class/ugp_ctrl/gp_scan_debug_switch/enable"));
                        gpiou.write("1");
                        gpiou.close();
                    }

                    FileWriter localFileWriter = new FileWriter(new File("/sys/class/ugp_ctrl/gp_sys_5v_ctrl/enable"));
                    localFileWriter.write("0");
                    localFileWriter.close();

                    IccManager mIccManager = new IccManager();
                    int status0 = mIccManager.open((byte) 0, (byte) 1, (byte) 1);
                    mIccManager.close();
                    gpiokey = false;
                    return false;
                }
            } catch (IOException localIOException) {
                localIOException.printStackTrace();
            }
        }
        gpiokey = false;
        return false;
    }

    public String ReadSAMID(String[] sRet) {
        String sSAMID = "";
        readtimeout = 0;
        boolean isTryOpen = false;
        Log.d(TAG, "" + PATH);

        try {
            if (!isOpen) {
                if (!openSerialPort(new File(PATH), BAUDRATE, 0))
                    return sSAMID;
                isTryOpen = true;
                isOpen = true;
            }
            Log.d(TAG, "ID " + sCmdReadSAMID);

            boolean bRet = SendAndRecv(sCmdReadSAMID, sRet, 300);
            Log.d(TAG,"bRet = "+ bRet);
            if (!bRet) return sSAMID;
            if (mBuffer[0] == (byte) 0x00 && mBuffer[1] == (byte) 0x00 && mBuffer[2] == (byte) 0x90) {
                String temp1 = DataUtils.toHexString1(mBuffer[3]);
                String temp2 = DataUtils.toHexString1(mBuffer[5]);
                byte[] temp3 = new byte[4];
                System.arraycopy(mBuffer, 7, temp3, 0, temp3.length);
                reversal(temp3);
                byte[] temp4 = new byte[4];
                System.arraycopy(mBuffer, 11, temp4, 0, temp4.length);
                reversal(temp4);
                byte[] temp5 = new byte[4];
                System.arraycopy(mBuffer, 15, temp5, 0, temp5.length);
                reversal(temp5);
                StringBuffer sb = new StringBuffer();
                sb.append(temp1);
                sb.append(".");
                sb.append(temp2);
                sb.append("-");
                sb.append(byte2Int(temp3));
                sb.append("-");
                String str4 = Long.toString(byte2Int(temp4));
                for (int i = 0; i < 10 - str4.length(); i++) {
                    sb.append("0");
                }
                sb.append(str4);
                sb.append("-");
                String str5 = Long.toString(byte2Int(temp5));
                for (int i = 0; i < 10 - str5.length(); i++) {
                    sb.append("0");
                }
                sb.append(str5);
                sSAMID = sb.toString();
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (isTryOpen) {
                isOpen = false;
                closeSerialPort();
            }
        }
        return sSAMID;
    }

    public IDCardInfo ReadBaseCardInfo(String[] sRet) {
        //	readtimeout=0;
        if (!isOpen) return null;
//		if(this.FindCard(sRet) && this.SelectCard(sRet))
//		{
//			if(this.ReadCardBase(sRet))
//			{				
//				return decodeInfo(mBuffer, false, true);				
//			}			
//		}
        Log.d(TAG, "qqqqqqqqqqqqqqqqqq");

        this.FindCard(sRet);
        this.SelectCard(sRet);
        if (this.ReadCardBase(sRet)) {
            Log.d(TAG, "bbbbbbbbbbbbbbbbbbbb");

            return decodeInfo(mBuffer, false, true);
        }
        return null;
    }

    public IDCardInfo ReadAllCardInfo(String[] sRet) {
//		if(!isOpen)	return null;
//		
//		if(this.FindCard(sRet) && this.SelectCard(sRet))
//		{
//			String sNewAddress = "";
//			if(ReadCardNewAddress(sRet))
//			{	
//				try 
//				{
//					sNewAddress = new String(mBuffer, 3, 70, "UTF-16LE").trim();
//				} 
//				catch (UnsupportedEncodingException e) 
//				{
//					e.printStackTrace();
//				}	  			
//			}
//			if(this.ReadCardFinger(sRet))
//			{				
//				IDCardInfo info = decodeInfo(mBuffer, true, true);
//				if(info != null)
//					info.setNewAddress(sNewAddress);
//				return info;				
//			}
//		}
//		return null;
        IDCardInfo info = null;
        readtimeout = 0;
        if (!isOpen) return null;
        this.FindCard(sRet);
        this.SelectCard(sRet);

        if (this.ReadCardFinger(sRet)) {
            info = decodeInfo(mBuffer, true, true);
            if (info == null) return null;
        }

        String sNewAddress = "";
        if (ReadCardNewAddress(sRet)) {
            try {
                sNewAddress = new String(mBuffer, 3, 70, "UTF-16LE").trim();
                Log.i("urovo", "sNewAddress:" + sNewAddress);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        if (info != null)
            info.setNewAddress(sNewAddress);
        return info;
    }


    private boolean FindCard(String[] sRet) {

        Log.d(TAG, " FindCard");

        boolean bRet = SendAndRecv(sCmdFindCard, sRet, 100);
        if (!bRet) return false;
        if (sRet[0].equalsIgnoreCase(sFIND_SUCC)) return true;
        return false;
    }

    private boolean SelectCard(String[] sRet) {
        Log.d(TAG, " SelectCard");

        boolean bRet = SendAndRecv(sCmdSelectCard, sRet, 100);
        if (!bRet) return false;
        if (sRet[0].equalsIgnoreCase(sSELECT_SUCC)) return true;
        return false;
    }

    private boolean ReadCardBase(String[] sRet) {
        Log.d(TAG, " ReadCardBase");

        boolean bRet = SendAndRecv(sCmdReadCardBase, sRet, 2000);
        if (!bRet) return false;
        if (mBuffer[0] == (byte) 0x00 && mBuffer[1] == (byte) 0x00 && mBuffer[2] == (byte) 0x90)
            return true;
        return false;
    }

    private boolean ReadCardFinger(String[] sRet) {
        boolean bRet = SendAndRecv(sCmdReadCardFinger, sRet, 3000);
        if (!bRet) return false;
        if (mBuffer[0] == (byte) 0x00 && mBuffer[1] == (byte) 0x00 && mBuffer[2] == (byte) 0x90)
            return true;
        return false;
    }

    private boolean ReadCardNewAddress(String[] sRet) {
        boolean bRet = SendAndRecv(sCmdReadNewAddress, sRet, 1500);
        Log.i("wujinquan", "ReadCardNewAddress:" + bRet);
        if (!bRet) return false;
        Log.i("wujinquan", "mBuffer[0]:" + mBuffer[0] + "  mBuffer[1]:" + mBuffer[1] + "   mBuffer[2]:" + mBuffer[2]);
        if (mBuffer[0] == (byte) 0x00 && mBuffer[1] == (byte) 0x00 && mBuffer[2] == (byte) 0x90)
            return true;
        return false;
    }


    private IDCardInfo decodeInfo(byte[] buffer, boolean haveFinger, boolean decodePhoto) {
        IDCardInfo people = new IDCardInfo();
        String temp = null;

        int nPtr = 3;
        short textSize = DataUtils.getShort(buffer[nPtr + 0], buffer[nPtr + 1]);
        short imageSize = DataUtils.getShort(buffer[nPtr + 2], buffer[nPtr + 3]);
        short fingerSize = 0;
        if (haveFinger) {
            fingerSize = DataUtils.getShort(buffer[nPtr + 4], buffer[nPtr + 5]);
            nPtr += 6;
        } else nPtr += 4;


        byte[] text = new byte[textSize];
        System.arraycopy(buffer, nPtr, text, 0, textSize);

        if (decodePhoto) {
            byte[] image = new byte[imageSize];
            System.arraycopy(buffer, nPtr + textSize, image, 0, imageSize);
            //people.setPhoto(parsePhoto(image));
            parsePhoto(image);
        }

        byte[] finger = null;
        if (fingerSize > 0) {
            finger = new byte[fingerSize];
            System.arraycopy(buffer, nPtr + textSize + imageSize, finger, 0, fingerSize);
            people.setFingerInfo(finger);
        }

        try {
            // ����
            temp = new String(text, 0, 30, "UTF-16LE").trim();
            people.setName(temp);

            // �Ա�
            temp = new String(text, 30, 2, "UTF-16LE");
            if (temp.equals("1"))
                temp = "男";
            else
                temp = "女";
            people.setGender(temp);

            // ����
            temp = new String(text, 32, 4, "UTF-16LE");
            try {
                int code = Integer.parseInt(temp.toString());
                temp = parseNation(code);
            } catch (Exception e) {
                temp = "";
            }
            people.setNation(temp);

            // ����
            temp = new String(text, 36, 16, "UTF-16LE").trim();
            people.setBirthday(temp);

            // סַ
            temp = new String(text, 52, 70, "UTF-16LE").trim();
            people.setAddress(temp);

            // ���֤��
            temp = new String(text, 122, 36, "UTF-16LE").trim();
            people.setCardNum(temp);

            // ǩ�����
            temp = new String(text, 158, 30, "UTF-16LE").trim();
            people.setRegistInstitution(temp);

            // ��Ч��ʼ����
            temp = new String(text, 188, 16, "UTF-16LE").trim();
            people.setValidStartDate(temp);

            // ��Ч��ֹ����
            temp = new String(text, 204, 16, "UTF-16LE").trim();
            people.setValidEndDate(temp);

        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
            return null;
        }
        return people;
    }

    private byte[] ReadSAMIDBuf(String[] sRet) {

        boolean bRet = SendAndRecv(sCmdReadSAMID, sRet, 300);

        if (!bRet) return null;
        if (mBuffer[0] == (byte) 0x00 && mBuffer[1] == (byte) 0x00 && mBuffer[2] == (byte) 0x90) {
            byte[] tmp = new byte[16];
            System.arraycopy(mBuffer, 3, tmp, 0, tmp.length);
            return tmp;
        }
        return null;
    }

    private boolean SendAndRecv(String sSendCmd, String[] sRecvResp, int nWaitTime) {
        int nLen = 0;
        if (!isOpen) return false;
        sRecvResp[0] = "";
        Arrays.fill(mBuffer, (byte) 0);
        byte[] bTmp;
        try {
            Log.d("A9LReader", "write++++++++++++++++++++++++++++++++++++");
            write(DataUtils.hexStringToBytes(sSendCmd));
            Log.d("A9LReader", "write/read------------------------------------------------------------------");
            int nRet = read(mBuffer, 7, nWaitTime);
            Log.d("A9LReader", "read------------------------------------------------------------------");
            if (nRet != 0) {
                sRecvResp[0] = "read err1:" + String.valueOf(nRet);
                return false;
            }
            bTmp = new byte[7];
            System.arraycopy(mBuffer, 0, bTmp, 0, bTmp.length);
            sRecvResp[0] = DataUtils.bytesToHexString(bTmp);

            if (mBuffer[0] == (byte) 0xaa && mBuffer[1] == (byte) 0xaa && mBuffer[2] == (byte) 0xaa && mBuffer[3] == (byte) 0x96 && mBuffer[4] == (byte) 0x69) {
                nLen = DataUtils.getShort(mBuffer[5], mBuffer[6]);
                nRet = read(mBuffer, nLen, nWaitTime);
                if (nRet != 0) {
                    sRecvResp[0] = "read err2:" + String.valueOf(nRet);
                    return false;
                }

                bTmp = new byte[nLen];
                System.arraycopy(mBuffer, 0, bTmp, 0, bTmp.length);
                sRecvResp[0] += DataUtils.bytesToHexString(bTmp);
                return true;
            } else sRecvResp[0] = "read err3";
        } catch (IOException e) {
            e.printStackTrace();
            sRecvResp[0] = e.getMessage();
        }
        return false;
    }


    private void reversal(byte[] data) {
        int length = data.length;
        for (int i = 0; i < length / 2; i++) {
            byte temp = data[i];
            data[i] = data[length - 1 - i];
            data[length - 1 - i] = temp;
        }
    }

    private long byte2Int(byte[] data) {
        int intValue = 0;
        for (int i = 0; i < data.length; i++) {
            intValue += (data[i] & 0xff) << (8 * (3 - i));
        }
        long temp = intValue;
        temp <<= 32;
        temp >>>= 32;
        return temp;
    }

}
